"""
Case Type   : 操作系统类-文件系统故障
Case Name   : switchover时，原主机+新主机注入故障文件系统硬连接满
Create At   : 2021/7/30
Owner       : @wan005
Description :
    1、原主机+新主机注入文件系统硬连接满故障
    2、备节点上执行gs_ctl switchover
    3、清理故障，
    4、执行TPCC
    5、检查数据一致性
    6、恢复环境
Expect      :
    1、故障注入成功
    2、switchover成功
    3、清理故障成功
    4、执行TPCC成功
    5、数据一致
    6、恢复环境
History     :
"""
import time
import unittest

from testcase.utils.ComThread import ComThread
from testcase.utils.Common import Common
from testcase.utils.CommonSH import CommonSH
from testcase.utils.CommonSH import RestartDbCluster
from testcase.utils.Constant import Constant
from testcase.utils.Logger import Logger
from yat.test import Node, macro


class ReliabilityFileSystem(unittest.TestCase):
    nodes = ("PrimaryDbUser", "Standby1DbUser", "Standby2DbUser")

    @RestartDbCluster(*nodes)
    def setUp(self):
        self.log = Logger()
        self.primary_sh = CommonSH(self.nodes[0])
        self.sta1_sh = CommonSH(self.nodes[1])
        self.primary_root_node = Node(node="PrimaryRoot")
        self.sta1_root_node = Node(node="Standby1Root")
        self.sta1_node = Node(node="Standby1DbUser")
        self.constant = Constant()
        self.com = Common()
        self.log.info("setUp-实例化:ok")

        self.log.info("Opengauss_Reliability_OS_File_System_Case032:开始执行")
        self.file_name = f"{macro.DB_INSTANCE_PATH}/postgresql.conf"
        self.inject_cmd = f"rfile_ldeplenish_workmode " \
                          f"(filename, workmode) " \
                          f"values ({self.file_name}, fore)"
        self.clean_cmd = f"rfile_ldeplenish_workmode where " \
                         f"filename={self.file_name} and workmode=fore"

    def test_main(self):
        try:
            self.log.info("--step1:原主机+新主机注入文件系统硬连接满故障;expect:成功")
            self.log.info("注入故障")
            session1 = ComThread(self.com.cfe_inject,
                                 args=(self.primary_root_node,
                                       self.inject_cmd))
            session1.setDaemon(True)
            session1.start()

            session2 = ComThread(self.com.cfe_inject,
                                 args=(self.sta1_root_node,
                                       self.inject_cmd))
            session2.setDaemon(True)
            session2.start()

            session1.join(60)
            result = session1.get_result()
            self.log.info(result)
            self.assertIn("successful execution", result)

            session2.join(60)
            result = session2.get_result()
            self.log.info(result)
            self.assertIn("successful execution", result)

            self.log.info("--step2:备节点上执行gs_ctl switchover;expect:成功")
            result = self.sta1_sh.executeGsctl("switchover",
                                               "switchover completed",
                                               get_detail=True)
            self.log.info(result)
            self.assertNotIn("No space left on device", result)
            self.assertIn("switchover completed", result)

        finally:
            self.log.info("--step3:清除故障;expect:成功")
            result = self.com.cfe_clean(self.primary_root_node,
                                        self.clean_cmd)
            self.log.info(result)
            self.assertIn("successful execution", result)

            result = self.com.cfe_clean(self.sta1_root_node,
                                        self.clean_cmd)
            self.log.info(result)
            self.assertIn("successful execution", result)

        status = self.sta1_sh.exec_refresh_conf()
        self.assertTrue(status)

        db_status = self.primary_sh.getDbClusterStatus("detail")
        self.log.info(db_status)
        self.assertTrue("Degraded" in db_status or "Normal" in db_status)
        self.assertTrue("S Primary" in db_status
                        and "P Standby" in db_status)

        self.log.info("--step4:运行TPCC;expect:成功")
        result = self.com.startTPCC(self.sta1_root_node, macro.TPCC_PATH)
        self.log.info(result)
        self.assertIn(self.constant.TPCC_SUCCESS_MSG, result)

        self.log.info("检查主备是否同步")
        time.sleep(10)
        self.log.info("获取节点数量")
        node_num = self.sta1_sh.get_node_num()
        res = self.sta1_sh.check_location_consistency("primary", node_num)
        self.assertTrue(res)

        self.log.info("--step5:检查数据一致性;expect:成功")
        nodes = (Node(self.nodes[0]), Node(self.nodes[1]),
                 Node(self.nodes[2]))
        flag = self.com.check_data_sample_by_all(r'\d', *nodes)
        self.assertTrue(flag)
        table_dict = self.com.format_sql_result(
            self.sta1_sh.executDbSql(r'\d'))
        table_name = table_dict.get('Name')
        for name in table_name:
            select_sql = f"select count(*) from {name};"
            flag = self.com.check_data_sample_by_all(select_sql, *nodes)
            self.assertTrue(flag)

    def tearDown(self):
        self.log.info("--step6:环境清理;expect:成功")
        res = self.com.cfe_clean(self.primary_root_node,
                                 self.clean_cmd)
        self.log.info(res)
        res1 = self.com.cfe_clean(self.sta1_root_node,
                                  self.clean_cmd)
        self.log.info(res1)
        self.log.info("故障已清理")

        db_status = self.primary_sh.getDbClusterStatus("detail")
        self.log.info(db_status)
        if "S Primary" in db_status or "P Standby" in db_status:
            result = self.primary_sh.executeGsctl("switchover",
                                                  "switchover completed",
                                                  get_detail=True)
            self.log.info(result)
            status = CommonSH(self.nodes[0]).exec_refresh_conf()
            self.log.info(status)
        db_status = self.primary_sh.getDbClusterStatus("detail")
        self.log.info(db_status)
        self.assertIn("successful execution", res)
        self.assertIn("successful execution", res1)
        self.log.info("Opengauss_Reliability_OS_File_System_Case032:执行完成")
